package br.com.iswe.gerador.velocity.gerador;

import java.io.File;
import java.io.FileWriter;
import java.io.Writer;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;

import br.com.iswe.gerador.velocity.info.InfoEntidadeImpl;
import br.com.iswe.gerador.velocity.info.InfoGerador;
import br.com.iswe.gerador.velocity.patterns.JSFPattern;

public class GeradorWBean extends GeradorBase {

	private static final String JAVA = ".java";

    private static final String TRUE = "true";

	private static final String GERADOR_WBEAN_PASTA_SAIDA = "gerador.wbean.pasta.saida";

	private static final String WBEAN_ABSTRACT_VM = "WBEAN-ABSTRACT.vm";

	private static final String WBEAN_IMPL_VM = "WBEAN-IMPL.vm";

	private static final String MANTER_WBEAN_ABSTRACT_VM = "MANTER-WBEAN-ABSTRACT.vm";

	private static final String MANTER_WBEAN_IMPL_VM = "MANTER-WBEAN-IMPL.vm";

	private static final String POPUP_WBEAN_ABSTRACT_VM = "POPUP-WBEAN-ABSTRACT.vm";

	private static final String POPUP_WBEAN_IMPL_VM = "POPUP-WBEAN-IMPL.vm";

	private static final String PACOTE_WBEAN = "PacoteWBean";

	public static final String GERADOR_WBEAN_PACKAGE_TO = "gerador.wbean.package.to";

	public static final String GERADOR_WBEAN_PACKAGE_FROM = "gerador.wbean.package.from";

	public static final String NOME_GERADOR = "geradorWBean";

	private InfoGerador infoGerador;

	public void gerarCodigo(InfoEntidadeImpl infoEntidade) throws Exception {
		// Primeiro Passo : Cria o contexto com as informa��es necess�rias para
		// criar a classe de BO.
		VelocityContext ctx = buildContext(this.infoGerador);
        JSFPattern jsfPattern = new JSFPattern();
        //Obtem o pacote para objetos abstratos
        String pacoteAbstrato = infoGerador.getPacoteAbstratos();
        
		// Obt�m o Pakage do componente :
		String packageWBean = infoEntidade.getReplacePackage(GERADOR_WBEAN_PACKAGE_FROM, GERADOR_WBEAN_PACKAGE_TO);
		ctx.put(PACOTE_WBEAN, packageWBean);
		// Adiciona a info da entidade
		ctx.put(InfoEntidadeImpl.NOME_INFO, infoEntidade);
		// Obt�m o package do BO que � necess�rio na classe WBean
		String fullPackageBO = infoEntidade.getReplacePackage(GeradorBO.GERADOR_BO_PACKAGE_FROM, GeradorBO.GERADOR_BO_PACKAGE_TO);
		infoEntidade.setPropriedade("fullPackageBO", fullPackageBO);

		// Segundo Passo : Obt�m o diret�rio onde ser� gerado o fonte de sa�da.
		String basePath = infoGerador.getPastaBaseSaida() + SEPARADOR + infoGerador.getPropriedade(GERADOR_WBEAN_PASTA_SAIDA);
		File pathSaida = new File(basePath + SEPARADOR + infoGerador.getPathFromPackage(packageWBean));
		// Verifica se o path ja existe
		if (!pathSaida.exists()) {
			pathSaida.mkdirs();
		}
        
        //verifica se existe a pasta de abstratos
        File pastaAbstratos = new File(pathSaida.getAbsolutePath() + SEPARADOR + pacoteAbstrato);
        if(!pastaAbstratos.exists()){
            pastaAbstratos.mkdirs();
        }

		String arquivoSaida = null;
		Template template = null;
		Writer wrt = null;
		// Quarto Passo : Obt�m o Template do BO e gera a sa�da.
		// Gerando a classe abstrata do WBean
		arquivoSaida = pastaAbstratos.getAbsolutePath() + SEPARADOR + jsfPattern.getWBeanAbstractName(infoEntidade) + JAVA;
        if( infoGerador.shouldGenerateFile(arquivoSaida) ){
			template = Velocity.getTemplate(WBEAN_ABSTRACT_VM);
			// Escreve o arquivo de sa�da
			wrt = new FileWriter(arquivoSaida);
			// Gera o documento.
			template.merge(ctx, wrt);
			// Descarrega para o disco.
			wrt.flush();
			wrt.close();
        }

        arquivoSaida = pathSaida.getAbsolutePath() + SEPARADOR + jsfPattern.getWBeanImplName(infoEntidade) + JAVA;
        if( infoGerador.shouldGenerateFile(arquivoSaida) ){
			// Gerando a classe concreta do WBean
			template = Velocity.getTemplate(WBEAN_IMPL_VM);
			// Escreve o arquivo de sa�da
			wrt = new FileWriter(arquivoSaida);
			// Gera o documento.
			template.merge(ctx, wrt);
			// Descarrega para o disco.
			wrt.flush();
			wrt.close();
		}

        arquivoSaida = pathSaida.getAbsolutePath() + SEPARADOR + jsfPattern.getManterWBeanImplName(infoEntidade) + JAVA;
        if( infoGerador.shouldGenerateFile(arquivoSaida) ){
			// Gerando a classe abstrata do WBean Manter
			template = Velocity.getTemplate(MANTER_WBEAN_IMPL_VM);
			// Escreve o arquivo de sa�da
			wrt = new FileWriter(arquivoSaida);
			// Gera o documento.
			template.merge(ctx, wrt);
			// Descarrega para o disco.
			wrt.flush();
			wrt.close();
		}

        arquivoSaida = pastaAbstratos.getAbsolutePath() + SEPARADOR + jsfPattern.getManterWBeanAbstractName(infoEntidade) + JAVA;
        if( infoGerador.shouldGenerateFile(arquivoSaida) ){
			// Gerando a classe concreta do WBean Manter
			template = Velocity.getTemplate(MANTER_WBEAN_ABSTRACT_VM);
			// Escreve o arquivo de sa�da
			wrt = new FileWriter(arquivoSaida);
			// Gera o documento.
			template.merge(ctx, wrt);
			// Descarrega para o disco.
			wrt.flush();
			wrt.close();
        }
		
		// Verifica se a entidade � refer�ncia de cole��o em alguma outra
		// entidade.
		if (TRUE.equals(infoEntidade.getPropriedade(InfoEntidadeImpl.IS_COLL_REF)) 
				|| TRUE.equals(infoEntidade.getPropriedade(InfoEntidadeImpl.IS_OBJ_REF))
				|| TRUE.equals(infoEntidade.getPropriedade(InfoEntidadeImpl.IS_COLL_REF_DETAIL))) {
			
			arquivoSaida = pastaAbstratos.getAbsolutePath() + SEPARADOR + jsfPattern.getPopUpWBeanAbstractName(infoEntidade) + JAVA;
	        if( infoGerador.shouldGenerateFile(arquivoSaida) ){
				// Gerando a classe abstrata do WBean PopUp
				template = Velocity.getTemplate(POPUP_WBEAN_ABSTRACT_VM);
				// Escreve o arquivo de sa�da
				wrt = new FileWriter(arquivoSaida);
				// Gera o documento.
				template.merge(ctx, wrt);
				// Descarrega para o disco.
				wrt.flush();
				wrt.close();
	        }

			// Gerando a classe concreta do WBean PopUp
	        arquivoSaida = pathSaida.getAbsolutePath() + SEPARADOR + jsfPattern.getPopUpWBeanImplName(infoEntidade) + JAVA;
	        if( infoGerador.shouldGenerateFile(arquivoSaida) ){
				template = Velocity.getTemplate(POPUP_WBEAN_IMPL_VM);
				// Escreve o arquivo de sa�da
				wrt = new FileWriter(arquivoSaida);
				// Gera o documento.
				template.merge(ctx, wrt);
				// Descarrega para o disco.
				wrt.flush();
				wrt.close();
			}
		}
	}

	public void inicio(InfoGerador infoGerador) {
		this.infoGerador = infoGerador;
	}

	public void fim() {
		this.infoGerador = null;
	}
}